//
//  ClipOperation.swift
//  MacVideoClip
//
//  Created by delouch on 2024/10/7.
//

import AVFoundation
import Foundation

class ClipOperation: Operation {

    override var isExecuting: Bool{
        return _executing
    }
    override var isFinished: Bool{
        return _finished
    }
    override var isAsynchronous: Bool{
        return true
    }

    //指定用于记录任务是否执行
    private var _executing:Bool = false{
    //kvo isExecuting
        willSet{
            willChangeValue(forKey: ModifyState.isExecuting.rawValue)
        }
        didSet{
            didChangeValue(forKey: ModifyState.isExecuting.rawValue)
        }
    }
    //指定用于记录任务是否完成
    private var _finished:Bool = false{
     //kvo isFinished
        willSet{
            willChangeValue(forKey: ModifyState.isFinished.rawValue)
        }
        didSet{
            didChangeValue(forKey: ModifyState.isFinished.rawValue)
        }
    }
        /// 修改状态枚举(重写状态的字段标识)
    private enum ModifyState: String{
        case isExecuting = "isExecuting"
        case isFinished = "isFinished"
    }

    override func start() {
        //检测取消状态
        if isCancelled{
            done()
            return
        }
        //修改状态->执行
        _executing = true
        //开启任务->并行,完成回调测试
        startTask()
    }
    
    private var file : FileInfo?
    
    init(file : FileInfo) {
        super.init()
        self.file = file
    }
    
    //开启任务
    private func startTask(){
        DispatchQueue.global().async { [weak self] in
            
            guard let weakSelf = self, let _file = weakSelf.file else { return }
            
            weakSelf.clipVideo(file: _file, step: 0)
            
        }
    }

    //重写取消
    override func cancel() {
        objc_sync_enter(self)
        done()
        objc_sync_exit(self)
    }
    
    //自定义cancel
    private func done() {
        super.cancel()
        if(_executing) {
            _finished = true
            _executing = false
        }
    }

    func clipVideo(file : FileInfo, step : Int) {
        let videoAsset : AVURLAsset = AVURLAsset(url: URL.init(filePath: file.path))
        guard let exportSession = AVAssetExportSession.init(asset: videoAsset, presetName: AVAssetExportPresetPassthrough) else {
            //检测状态
            if self.isCancelled{
                self.done()
                return
            }
            //完成
//            self.completionBlock?();
            self.done()
            return
        }
        let fileManager = FileManager.default
        let clipFold = file.fold + file.name + "/"
        if fileManager.fileExists(atPath: clipFold) == false {
            do {
                try fileManager.createDirectory(atPath: clipFold, withIntermediateDirectories: true)
            } catch {
                print("创建文件夹时发生错误: \(error)")
                //检测状态
                if self.isCancelled{
                    self.done()
                    return
                }
                //完成
//                self.completionBlock?();
                self.done()
                return
            }
        }
        exportSession.outputURL = URL.init(filePath: clipFold + file.name + String(format: "_%02d.", step + 1) + file.fileType)
        exportSession.outputFileType = .mp4
        exportSession.timeRange = CMTimeRange(start: CMTime(seconds: Double(step * 600), preferredTimescale: 600), end: CMTime(seconds: min(Double((step + 1) * 600) + 5, file.duration), preferredTimescale: 600))
        exportSession.exportAsynchronously(completionHandler: {
            switch exportSession.status {
            case .unknown:
                print("unknown")
            case .waiting:
                print("waiting")
            case .exporting:
                print("exporting")
            case .completed:
                if (step + 1) * 600 < Int(ceil(file.duration)) {
                    print(file.name + "_(\(step + 1))_完成")
                    self.clipVideo(file: file, step: step + 1)
                }else {
                    print(file.name + "_完成")
                    //检测状态
                    if self.isCancelled{
                        self.done()
                        return
                    }
                    self.done()
                }
            case .failed:
                print("failed")
            case .cancelled:
                print("cancelled")
            @unknown default:
                break
            }
        })
    }
    
}
